package com.jy.api.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jy.api.dao.*;
import com.jy.api.domain.*;
import com.jy.api.enums.OrderPayChannel;
import com.jy.api.enums.PayTypeEnum;
import com.jy.api.pay.request.PayRequest;
import com.jy.api.payReq.*;
import com.jy.api.service.StorePayService;
import com.jy.api.signUpReq.web.WebCancelPayReq;
import com.jy.api.util.*;
import com.thoughtworks.xstream.XStream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class HSServiceImpl implements StorePayService {
    @Autowired
    private PaymentServiceImpl service;
    @Autowired
    private XStream xstream;
    @Autowired
    private AliyunMNSSend aliyunMNSSend;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private PaymentDao paymentDao;
    @Autowired
    private TransactionTemplate transactoinTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RewardDao rewardDao;
    @Autowired
    private StoreDao storeDao;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private RedisSyncLocker redisSyncLocker;
    @Autowired
    private AccountBalanceDao accountBalanceDao;
    @Value("${api.gateway.url}")
    private String baseURL;
    @Autowired
    private StorePayDao storePayDao;
    @Autowired
    private RestTemplate restTemplate;


    public AllPayBaseResult HuiShangPay(Order order, String authCode, Store store, String mchId) throws Exception {
        AllPayBaseResult payResult = micropay(order, authCode, mchId);
        log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{},订单内容{}", order.getStoreId(), order.getId(), "汇商支付开始", payResult, order);
        log.info("payResult" + payResult);
        order.setPayChannel(OrderPayChannel.HUI_SHANG);
        if (payResult.isSuccess()) {
            // 支付成功，更新订单状态
            Payment payment = service.createPaymentBySwiftPassResult(payResult, store.getId());
            // TODO: 2018/8/23  订单状态不应该区分是否履行。该平台可以不管理订单履行情况，因为一般都是线下履行
            if (OrderSource.POS == order.getSource()) {
                order.setStatus(OrderStatus.FINISHED);
            } else {
                order.setStatus(OrderStatus.UNFINISHED);
            }
            order.setPaymentTime(payment.getCreateTime());
            order.setPayId(payment.getId());
            order.setChannel(payResult.getTradeType());
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付成功", payResult);
            // 订单与支付信息的更新在同一个事务中
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    orderDao.save(order);
                    paymentDao.save(payment);
                }
            });
            service.postPaymentSuccess(order, store);

        } else if (payResult.isFailed()) {
            // 支付失败，允许订单再次支付
            order.setStatus(OrderStatus.CANCELED);
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付失败", payResult);
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    orderDao.save(order);
                }
            });
        } else {
            // 支付结果不确定
            order.setStatus(OrderStatus.NOTSURE);
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    orderDao.save(order);
                }
            });
            log.info("门店{}, 订单号{}, 操作{}, 支付返回结果{}", order.getStoreId(), order.getId(), "支付结果不确定", payResult);
            aliyunMNSSend.sendClint(order.getId());
        }
        redisTemplate.opsForValue().set(order.getId(), order.getId(), 5, TimeUnit.SECONDS);
        return payResult;
    }

    public AllPayBaseQueryResult queryMicroPay(String orderId) {
        Order order = orderDao.findOne(orderId);
        StorePay store = storePayDao.findByStoreIdAndStartEnabled(order.getStoreId(), true);

        PayRequest payRequest = new PayRequest(PayTypeEnum.UNIFIED_TRADE_QUERY.getCode(),
                store.getMchId(), orderId);

        Map objectAsMap = objectMapper.convertValue(payRequest, Map.class);
        payRequest.setUpSign(objectAsMap, store.getMchKey());
        String requestXML = payRequest.toXML();
        log.info("The request body of payment query is:{}", requestXML);
        String xml = "";
        try {
            xml = OkHttpUtils.xmlPost(Payutils.ALI_QR_CODE, requestXML);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        log.info("The response body of payment query is:{}", xml);
        AllPayBaseQueryResult result = new AllPayBaseQueryResult();
        BeanUtils.copyProperties(xstream.fromXML(xml, new SwiftPassPaymentQueryBaseResult()), result);
        return result;
    }


    public void callbackForMicroPaymentFailed(String orderId, AllPayBaseQueryResult queryResult) throws Exception {
        Order order = orderDao.findOne(orderId);
        Reward reward = rewardDao.findOne(orderId);
        if (reward != null) {
            if (reward.getStatus().equals(OrderStatus.INIT)) {
                // 说明已经处理过支付失败的情况
                return;
            } else {
                // 支付失败后订单返回未结算状态，允许再次结算
                reward.setStatus(OrderStatus.INIT);
                transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        rewardDao.save(reward);
                    }
                });
            }
        } else {
            if (order.getStatus().equals(OrderStatus.CANCELED)) {
                // 说明已经处理过支付失败的情况
                return;
            } else {
                // 支付失败后订单返回未结算状态，允许再次结算
                order.setStatus(OrderStatus.CANCELED);

                transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        orderDao.save(order);
                    }
                });
            }
        }
    }


    public AllPayReverseResult cancelPay(String orderId, WebCancelPayReq req) {
        Order order = orderDao.findOne(orderId);
        Reward reward = rewardDao.findOne(orderId);

        log.info("门店{}, 订单号{}, 操作{}, 操作内容{}, reward:{}", order.getStoreId(), order.getId(), "取消订单开始", order, reward);

        if (reward != null) {
            reward.setPayChannel(OrderPayChannel.HUI_SHANG);
            if (reward.getStatus().equals(OrderStatus.CANCELED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "该笔支付已经被取消");
                throw new RuntimeException("该笔支付已经被取消");
            } else if (reward.getStatus().equals(OrderStatus.UNFINISHED) || reward.getStatus().equals(OrderStatus.FINISHED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "已经成功支付，取消支付操作被中止。");
                throw new RuntimeException("已经成功支付，取消支付操作被中止。");
            } else {
                StorePay store = storePayDao.findByStoreIdAndStartEnabled("574b59ef-b19c-11e7-9233-37891743d141", true);
                AllPayBaseResult paymentResult = service.queryMicroPay(reward.getId());
                if (paymentResult.isSuccess()) {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "已经成功支付，取消支付操作被中止(火星云)。");
                    throw new RuntimeException("已经成功支付，取消支付操作被中止。");
                }
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "优先调用撤消订单接口");
                AllPayReverseResult result = service.reversePayment(store.getMchId(), reward.getId(), store.getMchKey(), req);
                if (result.isSuccess()) {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            reward.setStatus(OrderStatus.CANCELED);
                            rewardDao.save(reward);
                        }
                    });
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "撤消成功");
                    return result;
                } else {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "撤消失败调用关闭订单接口");
                    // 撤销失败，调用关闭订单接口
                    result = service.closePayment(store.getMchId(), reward.getId(), store.getMchKey());
                    if (result.isSuccess()) {
                        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                            @Override
                            protected void doInTransactionWithoutResult(TransactionStatus status) {
                                reward.setStatus(OrderStatus.CANCELED);
                                rewardDao.save(reward);
                            }
                        });
                        log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "调用关闭订单接口成功");
                        return result;
                    } else {
                        log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "调用关闭订单接口失败：" + result.getErrMsg());
                        throw new RuntimeException(result.getErrMsg());
                    }
                }
            }
        } else {
            if (order.getStatus().equals(OrderStatus.CANCELED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "支付已经被取消，请到订单列表查询确认");
                throw new RuntimeException("支付已经被取消，请到订单列表查询确认");
            } else if (order.getStatus().equals(OrderStatus.UNFINISHED) || order.getStatus().equals(OrderStatus.FINISHED)) {
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
                throw new RuntimeException("订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
            } else {
                StorePay store = storePayDao.findByStoreIdAndStartEnabled(order.getStoreId(), true);
                AllPayBaseResult paymentResult = service.queryMicroPay(orderId);
                order.setPayChannel(OrderPayChannel.HUI_SHANG);
                if (paymentResult.isSuccess()) {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
                    throw new RuntimeException("订单已经成功支付，取消支付操作被中止。请到订单列表查询确认");
                }
                log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "优先调用撤消订单接口");
                // 先调用撤销订单接口
                AllPayReverseResult result = service.reversePayment(store.getMchId(), orderId, store.getMchKey(), req);
                if (result.isSuccess()) {
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setStatus(OrderStatus.CANCELED);
                            orderDao.save(order);
                        }
                    });
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "撤消成功");
                    return result;
                } else {
                    log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "撤消失败调用关闭订单接口");
                    // 撤销失败，调用关闭订单接口
                    result = service.closePayment(store.getMchId(), orderId, store.getMchKey());
                    if (result.isSuccess()) {
                        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                            @Override
                            protected void doInTransactionWithoutResult(TransactionStatus status) {
                                order.setStatus(OrderStatus.CANCELED);
                                orderDao.save(order);
                            }
                        });
                        log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "调用关闭订单接口成功");
                        return result;
                    } else {
                        log.info("门店{}, 订单号{}, 操作{}, 操作内容{}", order.getStoreId(), order.getId(), "取消订单", "调用关闭订单接口失败：" + result.getErrMsg());
                        throw new RuntimeException("取消支付失败，请稍后再试");
                    }
                }
            }
        }
    }

    public ALLPayQrCodeResult qrCodePay(String orderId, PayTypeEnum type) throws Exception {
        return (ALLPayQrCodeResult) redisSyncLocker.idLock(orderId, new ISyncExecutor() {
            @Override
            public Object execute(Object o) throws Exception {
                Order order = orderDao.findOne(orderId);
                StorePay store = storePayDao.findByStoreIdAndStartEnabled(order.getStoreId(), true);
                order.setPayChannel(OrderPayChannel.HUI_SHANG);
                //初始化请求实体
                PayRequest payRequest = new PayRequest(type.getCode(), store.getMchId(),
                        orderId, service.getBody(order),
                        (int) Math.rint(order.getAmount() * 100), "172.17.0.1",
                        baseURL + "/v1/pay/callBack");
                payRequest.setService("unified.trade.native");
                //这里是生成二维码的
                payRequest.setUpSign(objectMapper.convertValue(payRequest, Map.class), store.getMchKey());
                String requestBody = payRequest.toXML();
                log.info("The request body of QR code payment is:{}", requestBody);
                String xml = "";
                try {
                    xml = OkHttpUtils.xmlPost(Payutils.ALI_QR_CODE, payRequest.toXML());
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                log.info("The response XML of micro pay is:{}", xml);
                ALLPayQrCodeResult result = new ALLPayQrCodeResult();
                BeanUtils.copyProperties(xstream.fromXML(xml, new SwiftPassQRCodePayResult()), result);
                if (result.isSuccess()) {
                    // 更新订单状态到支付中，防止其被更新
                    transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                        @Override
                        protected void doInTransactionWithoutResult(TransactionStatus status) {
                            order.setStatus(OrderStatus.NOTSURE);
                            orderDao.save(order);
                        }
                    });
                }
                return result;
            }
        });
    }

    public ALLPayQrCodeResult qrRewardCodePay(String rewardId, PayTypeEnum type) {
        Reward reward = rewardDao.findOne(rewardId);
        StorePay store = storePayDao.findByStoreIdAndStartEnabled("574b59ef-b19c-11e7-9233-37891743d141", true);
        //初始化请求实体
        reward.setPayChannel(OrderPayChannel.HUI_SHANG);
        PayRequest payRequest = new PayRequest(type.getCode(), store.getMchId(),
                rewardId, service.getRewardBody(reward),
                (int) Math.rint(reward.getTotal() * 100), "172.17.0.1",
                baseURL + "/v1/pay/callBack");
        payRequest.setService("unified.trade.native");
        //这里是生成二维码的
        payRequest.setUpSign(objectMapper.convertValue(payRequest, Map.class), store.getMchKey());
        log.info("The request body of QR code payment is:{}", payRequest.toXML());
        String xml = "";
        try {
            xml = OkHttpUtils.xmlPost(Payutils.ALI_QR_CODE, payRequest.toXML());
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        log.info("The response body of QR code payment is:{}", xml);
        ALLPayQrCodeResult result = new ALLPayQrCodeResult();
        BeanUtils.copyProperties(xstream.fromXML(xml, new SwiftPassQRCodePayResult()), result);
        if (result.isSuccess()) {
            // 更新订单状态到支付中，防止其被更新
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    reward.setStatus(OrderStatus.NOTSURE);
                    rewardDao.save(reward);
                }
            });
        }
        return result;
    }

    public AllPayJsPayResult jsPay(StorePay storePay, String orderId, String openId) throws Exception {
        return (AllPayJsPayResult) redisSyncLocker.idLock(orderId, o -> {
            Order order = orderDao.findOne(orderId);
            //初始化请求实体
            order.setPayChannel(OrderPayChannel.HUI_SHANG);
            PayRequest payRequest = new PayRequest(PayTypeEnum.PAY_WEIXIN_JSPAY.getCode(),
                    //appid写死所有的均配置火星铺手的微信公众号
                    storePay.getMchId(), orderId, service.getBody(order), openId, "wxf6f45bc02f8e7de8",
                    (int) (order.getAmount() * 100), "172.18.0.1", baseURL + "/v1/pay/callBack");
            payRequest.setSign_agentno("10100000284");
            payRequest.setUpSign(objectMapper.convertValue(payRequest, Map.class), storePay.getMchKey());
            log.info("The request body of JSPAY is:{}", payRequest);
            String xml = "";
            try {
                xml = OkHttpUtils.xmlPost(Payutils.ALI_QR_CODE, payRequest.toXML());
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            log.info("The response body of JSPAY is:{}", xml);
            AllPayJsPayResult result = new AllPayJsPayResult();
            BeanUtils.copyProperties(xstream.fromXML(xml, new SwiftPassJSPayResult()), result);
            if (result.isSuccess()) {
                // 更新订单状态到支付中，防止其被更新
                transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                    @Override
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        order.setStatus(OrderStatus.NOTSURE);
                        orderDao.save(order);
                    }
                });
            }

            return result;
        });
    }


    public AllPayBaseResult micropay(Order order, String authCode, String mchId) {
        //初始化请求实体
        PayRequest payRequest = new PayRequest(PayTypeEnum.UNIFIED_TRADE_MICROPAY.getCode(), mchId,
                order.getId(), service.getBody(order),
                (int) Math.rint(order.getAmount() * 100), "172.17.0.1",
                "");
        payRequest.setAuth_code(authCode);
        // QQ钱包刷卡需要该字段
        payRequest.setDevice_info("iPhoneX");
        payRequest.setSign_agentno("10100000284");
        ObjectMapper objectMapper = new ObjectMapper();
        payRequest.setUpSign(objectMapper.convertValue(payRequest, Map.class), "h92Tz0wF6QX66hR4pM7VVdXD4NNS3cSO");


        log.info("The request XML of micro pay is:{}", payRequest.toXML());
        try {

            String xml = "";
            try {
                xml = OkHttpUtils.xmlPost(Payutils.ALI_QR_CODE, payRequest.toXML());
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            log.info("The response XML of micro pay is:{}", xml);
            String str = null;
            try {
                str = new String(xml.getBytes("iso8859-1"), "UTF-8");
            } catch (UnsupportedEncodingException e1) {
                e1.printStackTrace();
            }
            String[] whole = str.split("\n");
            String result = whole[whole.length - 1].replace("`", "");
            String[] total = result.split(",");
            log.info("The response XML of micro pay is:{}", result);
            log.info("The response XML of micro pay is:{}", total);
            AllPayBaseResult allPayBaseResult = new AllPayBaseResult();
            BeanUtils.copyProperties(xstream.fromXML(xml, new SwiftPassMicroPayBaseResult()), allPayBaseResult);
            return allPayBaseResult;
        } catch (ResourceAccessException e) {
            // IO error
            // 支付结果未知，将订单id加入轮训队列
            aliyunMNSSend.sendClint(order.getId());
            throw new RuntimeException("支付结果未知，请稍后到订单列表中查看结果");
        }

    }


    public void callbackForMicroPaymentSuccess(AllPayBaseQueryResult queryResult) throws Exception {
        Order order = orderDao.findOne(queryResult.getOutTradeNo());
        Reward reward = rewardDao.findOne(queryResult.getOutTradeNo());


        if (reward != null) {
            reward.setPayChannel(OrderPayChannel.HUI_SHANG);
            if (reward.getStatus().equals(OrderStatus.FINISHED) || reward.getStatus().equals(OrderStatus.UNFINISHED)) {
                // 已经处理过支付成功事件
                return ;
            }
            reward.setPaymentTime(MyDateUtils.getDateFormatDd(queryResult.getTimeEnd(), "yyyyMMddHHmmss"));
            reward.setChannel(queryResult.getTradeType());
            reward.setStatus(OrderStatus.FINISHED);
            AccountBalance accountBalance = accountBalanceDao.findByStoreId(reward.getStoreId());
            log.info("accountBalance" + accountBalance);
            if (accountBalance == null) {
                accountBalance = new AccountBalance(queryResult.getTotalFee() / 100.0, reward.getStoreId());
            } else {
                accountBalance.setAmount(accountBalance.getAmount() + queryResult.getTotalFee() / 100.0);
            }
            // 订单与支付信息的更新在同一个事务中
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    rewardDao.save(reward);

                }
            });
            accountBalanceDao.save(accountBalance);
            aliyunMNSSend.sendClint(reward.getId());
        } else {
            if (order.getStatus().equals(OrderStatus.FINISHED) || order.getStatus().equals(OrderStatus.UNFINISHED)) {
                // 已经处理过支付成功事件
                return ;
            }
            order.setPayChannel(OrderPayChannel.HUI_SHANG);
            Store store = storeDao.findOne(order.getStoreId());

            Payment payment = new Payment();
            payment.setId(queryResult.getTransactionId());
            payment.setOrderId(queryResult.getOutTradeNo());
            payment.setStoreId(order.getStoreId());
            payment.setSuccess(queryResult.isSuccess());
            payment.setStatus(PaymentStatus.SUCCESS);
            Date paymentTime = MyDateUtils.getDateFormatDd(queryResult.getTimeEnd(), "yyyyMMddHHmmss");
            payment.setCreateTime(paymentTime);
            payment.setAmount(queryResult.getTotalFee() / 100.0);
            payment.setChannel(queryResult.getTradeType());


            if (OrderSource.POS == order.getSource()) {
                order.setStatus(OrderStatus.FINISHED);
            } else {
                order.setStatus(OrderStatus.UNFINISHED);
            }
            order.setPaymentTime(payment.getCreateTime());
            order.setPayId(payment.getId());
            order.setChannel(queryResult.getTradeType());

            // 订单与支付信息的更新在同一个事务中
            transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    paymentDao.save(payment);
                    orderDao.save(order);
                }
            });

            service.postPaymentSuccess(order, store);
        }
    }

    public AllPayRefundQueryResult queryRefundResult(String refundOrderId) {
        Order order = orderDao.findOne(refundOrderId);
        order.setPayChannel(OrderPayChannel.HUI_SHANG);
        StorePay storePay = storePayDao.findByStoreIdAndStartEnabled(order.getStoreId(), true);
        AllPayRefundQueryResult result = new AllPayRefundQueryResult();
        PayRequest payRequest = new PayRequest(PayTypeEnum.UNIFIED_TRADE_REFUNDQUERY.getCode(), storePay.getMchId(), order);
        payRequest.setUpSign(objectMapper.convertValue(payRequest, Map.class), storePay.getMchKey());

        String requestBody = payRequest.toXML();
        log.info("The request body of refund query is:{}", requestBody);
        String xml = restTemplate.postForEntity(Payutils.ALI_QR_CODE, requestBody, String.class).getBody();
        log.info("The response body of refund query is:{}", xml);
        BeanUtils.copyProperties(xstream.fromXML(xml, new SwiftPassRefundQueryResult()), result);
        return result;
    }


    public void callbackForThirdPartyRefundSuccess(AllPayRefundQueryResult result) {
        log.debug("Step in callback for third party refund success...");
        Payment payment = paymentDao.findOne(result.getRefundId());
        payment.setStatus(PaymentStatus.SUCCESS);
        payment.setSuccess(true);

        Date paymentTime = MyDateUtils.getDateFormatDd(result.getRefundTime(), "yyyyMMddHHmmss");
        payment.setCreateTime(paymentTime);

        Order refundOrder = orderDao.findOne(payment.getOrderId());
        refundOrder.setPayChannel(OrderPayChannel.HUI_SHANG);
        refundOrder.setStatus(OrderStatus.REFUNDED);
        refundOrder.setPaymentTime(paymentTime);

        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                orderDao.save(refundOrder);
                paymentDao.save(payment);
            }
        });

        try {
            service.postRefundSuccess(refundOrder);
        } catch (Exception e1) {
            log.info(e1.toString());
        }
    }


    public void callbackForThirdPartyRefundFail(AllPayRefundQueryResult result) {
        Order refundOrder = orderDao.findOne(result.getOutRefundNo());
        refundOrder.setStatus(OrderStatus.INIT);
        refundOrder.setPayChannel(OrderPayChannel.HUI_SHANG);
        transactoinTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                orderDao.save(refundOrder);
            }
        });
    }

    public SwiftPassRefundResult refundPay(Order order, Payment payment, StorePay storePay) {
        // 三方支付退款
        PayRequest payRequest = new PayRequest(PayTypeEnum.UNIFIED_TRADE_REFUND.getCode(), storePay.getMchId(),
                order.getId(), order.getId(), (int) (payment.getAmount() * 100), (int) (payment.getAmount() * 100), storePay.getMchId());
        payRequest.setSign_agentno("10100000284");
        payRequest.setUpSign(objectMapper.convertValue(payRequest, Map.class), storePay.getMchKey());

        String requestBody = payRequest.toXML();
        log.info("The request body of payment refund is:{}", requestBody);

        String xml = restTemplate.postForEntity(Payutils.ALI_QR_CODE, requestBody, String.class).getBody();
        log.info("The response body of payment refund is:{}", xml);

        SwiftPassRefundResult result = (SwiftPassRefundResult) xstream.fromXML(xml, new SwiftPassRefundResult());
        return result;
    }

}
